# 读取数据,转换成数组方便计数，下面这行注释解决读文件时报的SyntaxError
# 这里特别注意加上header=None，不要把第一行当成表头
# encoding=utf-8
import pandas as pd
import numpy as np
def readData():
    data=pd.read_csv('house-votes-84.data',header=None)
    data=np.array(data)
    return data

# 查看帮助文件发现？可能代表没投票或者是未知态度，故不将其作为缺失数据对待，而将其作为未知态度对待，不计入频繁项集的统计中，
# 统计1.投票为y 2.投票为n 3.特定党派投票为y的 4.特定党派投票为n的  议题的index
def cindex(data,vote,party):
    cindex=[]
    for row in data:
        tmp=[]
        if(party==0 or (party!=0 and party==row[0])):
            for i in range(1,len(row)):
                if(row[i]==vote):
                    tmp.append(i)
        if(tmp==[]):
            continue
        cindex.append(tmp)
    return cindex

# 频繁项集的产生
# 1-频繁项集的产生
def fre_on(cindex,support):
    # 使用dict来存放频繁项集key表示的是议题的index，
    # value表示index对应议题的support(y/n)的数目，
    # 注：此实验注释中的support可以表示y/n，取决于vote的值
    fre_tmp={}
    # 统计不同index的support数目
    for row in cindex:
        for item in row:
            # 议题使用tuple来存，以便后续加入多个议题的index组成的频繁项集
            tmp=(item,)
            if tmp in fre_tmp:
                fre_tmp[tmp]+=1
            else:
                fre_tmp[tmp]=1
    minsup=int(support*len(cindex))
    # 选择support>=minsup的项集组成1-频繁项集，结果以{(index1,):support1,(index2,):support2...}形式存放
    fre_one={}
    for item in fre_tmp:
        if(fre_tmp[item]>=minsup):
            fre_one[item]=fre_tmp[item]
    return fre_one

def fre_onm(cindex,support,fre_oneb):
    fre_tmp={}
    for item1 in fre_oneb:
        for item2 in fre_oneb:
            if(item1!=item2):
                maxt=max(item1[-1],item2[-1])
                mint=min(item1[-1],item2[-1])
                # 合并的两个n-频繁项集的前n-1项要相等才能合并，并且在合并时需要按序合并
                if(item1[:-1]==item2[:-1]):
                    if(len(item1)==1):
                        fre_tmp[(mint,maxt)]=0
                    else:
                        tmp=list(item1[:-1])
                        fre_tmp[tuple(tmp+[mint,maxt])]=0
    # 对n+1-项集进行计数
    for row in cindex:
        for item in fre_tmp:
            tmp=item
            tmp1=row
            if(set(tmp).issubset(set(tmp1))):
                fre_tmp[item]+=1
    # 选择support＞minsup的项集作为n + 1 - 频繁项集，
    # 结果以{(index1,index2,index3...):support1,(index4,index5...):support2...}形式存放
    minsup=len(cindex)*support
    fre_onem={}
    for item in fre_tmp:
        if(fre_tmp[item]>=minsup):
            fre_onem[item]=fre_tmp[item]
    return fre_onem

# 形成最终的频繁项集
def fre_all(cindex,support,confidence):
    # 产生1-频繁项集
    fre_one=fre_on(cindex,support)
    fre_oneb=fre_one
    # 用于放n-频繁项集的dict
    # 最终的fre_al的形式类似于[{(index1,):1,(index2,):1,...},{(index1,index2):1,(index3,index4):1,...},{}...]
    fre_al=[]
    while(fre_oneb!={}):
        fre_al.append(fre_oneb)
        fre_oneb=fre_onm(cindex,support,fre_oneb)
    return fre_al

# 关联规则的产生
def rule(confidence,fre_al,minconf):
    rules=[]
    subset1={}
    # 从1-频繁项集开始遍历频繁项集
    for i in range(0,len(fre_al)):
        for freset in fre_al[i]:
            # subset1中存放在着遍历过的频繁项集
            # 当subset1中的频繁项集是正在遍历的频繁项集的子集时查看以subset1中频繁项集作为前项，
            # 正在遍历的频繁项集-subset1中的频繁项集作为后项的置信度，（即从关联规则格结构的底部开始往上遍历）
            # 若conf＞minconf则作为强关联规则保留下来结果以rules=[{indexs规则前项},{indexs规则后项},rule-conf]形式呈现
            for subfre in subset1:
              if(set(subfre).issubset(set(freset))):
                  conf=fre_al[i][freset]/subset1[subfre]
                  if(conf>=minconf):
                      trule=(set(subfre),set(freset)-set(subfre),conf)
                      rules.append(trule)
            subset1[freset]=fre_al[i][freset]
    return rules


# 以下是main程序

# 读取数据
data=readData()
# print(data)

# 统计1.投票为y 2.投票为n 3.特定党派投票为y的 4.特定党派投票为n的  人的index
datay_a=cindex(data,'y',0)
datan_a=cindex(data,'n',0)
datay_d=cindex(data,'y','democrat')
datan_d=cindex(data,'n','democrat')
datay_r=cindex(data,'y','republican')
datan_r=cindex(data,'n','republican')

# print('datay_all:',datay_a)
# print('datan_all:',datan_a)
# print('datay_democrat:',datay_d)
# print('datan_democrat:',datan_d)
# print('datay_republican:',datay_r)
# print('datan_republican:',datan_r)

# 设置参数
support=0.3
confidence=0.9

# 频繁项集
frey_all=fre_all(datay_a,support,confidence)
fren_all=fre_all(datan_a,support,confidence)
frey_d=fre_all(datay_d,support,confidence)
fren_d=fre_all(datan_d,support,confidence)
frey_r=fre_all(datay_r,support,confidence)
fren_r=fre_all(datan_r,support,confidence)

# 按行打印出频繁项集
# print('republican的反对的频繁项集:\n')
# print('项集 support\n')
# for i in range(0,len(fren_r)):
#     print(i+1,'-频繁项集')
#     for item in fren_r[i]:
#         print(item,':',fren_r[i][item],',')
#     print('\n')

print('全部数据的支持的频繁项集：',frey_all)
print('全部数据的反对的频繁项集：',fren_all)
print('democrat的支持的频繁项集：',frey_d)
print('democrat的反对的频繁项集：',fren_d)
print('republican的支持的频繁项集：',frey_r)
print('republican的反对的频繁项集：',fren_r)

# 挖掘规则
ruley_a=rule(confidence,frey_all,confidence)
rulen_a=rule(confidence,fren_all,confidence)
ruley_d=rule(confidence,frey_d,confidence)
rulen_d=rule(confidence,fren_d,confidence)
ruley_r=rule(confidence,frey_r,confidence)
rulen_r=rule(confidence,fren_r,confidence)

# 将关联规则按行输出
# print('republican有关反对的规则:\n')
# print('规则前项 规则后项 confidence\n')
# for i in range(0,len(rulen_r)):
#     print(rulen_r[i])

print('所有有关支持的规则',ruley_a)
print('所有有关反对的规则',rulen_a)
print('democrat有关支持的规则',ruley_d)
print('democrat有关反对的规则',rulen_d)
print('republican有关支持的规则',ruley_r)
print('republican有关反对的规则',rulen_r)



